

local Timer = commonlib.inherit(nil, {});

local __system_timer_interval__ = commonlib.GetTimerInterval();
local __current_timestamp__ = commonlib.GetTimeStamp();

local __timers__ = {};

function Timer:ctor()
end

function Timer:Init(delay, interval, callback, use_virtual_timestamp)
    if (type(callback) ~= "function") then return end 
    self.__delay__ = delay;
    self.__interval__ = interval;
    self.__callback__ = callback;
    self.__use_virtual_timestamp__ = use_virtual_timestamp;

    return self;
end

function Timer:Refresh()
    if (not self.__delay__ and not self.__interval__) then return self:Stop() end 
    local interval = self.__delay__ or self.__interval__ or 0;
    local curtime = self.__use_virtual_timestamp__ and __current_timestamp__ or commonlib.GetTimeStamp();
    self.__callback_at__ = curtime + interval;
    self.__delay__ = nil;
    return self;
end

function Timer:Start()
    self:Refresh();
    __timers__[self] = self;
    return self;
end

function Timer:Stop()
    __timers__[self] = nil;
end

function Timer:Activate(curtime)
    curtime = self.__use_virtual_timestamp__ and __current_timestamp__ or curtime;
    if (curtime < self.__callback_at__) then return end 

    self.__callback__(self);
    self:Refresh();
end

commonlib.GetVirtualTimeStamp = function()
    return __current_timestamp__;
end

commonlib.SetTimeout = function(delay, callback, virtual_timestamp)
    return Timer:new():Init(delay or 0, nil, callback, virtual_timestamp):Start();
end

commonlib.ClearTimeout = function(timer)
    timer:Stop();
end

commonlib.SetInterval = function(interval, callback, virtual_timestamp) 
    return Timer:new():Init(nil, interval or 0, callback, virtual_timestamp):Start();
end

commonlib.ClearInterval = function(timer)
    timer:Stop();
end

-- C++ CallBack
_G.__on_timer__ = commonlib.__xpcall_callback__(function()
    local curtime = commonlib.GetTimeStamp();
    __current_timestamp__ = __current_timestamp__ + __system_timer_interval__;
    for _, timer in ipairs(commonlib.values(__timers__)) do
        timer:Activate(curtime);
    end
end)

return Timer;